Like any kind of apps, JavaScript apps also have to be written well.
Otherwise, we run into all kinds of issues later on.
In this article, we’ll look at ways to improve our JavaScript code.
Unportable Scoping of Block Function Declarations
We shouldn’t have function declarations inside a block.
This isn’t valid JavaScript but it’s still allowed by most JavaScript engines.
This is because we have problems with the results that it produces.
If we have:
function foo(x) {
function f() {
return "bar";
}
var result = [];
if (x) {
result.push(f());
}
result.push(f());
return result;
}
console.log(foo(true));
console.log(foo(false));
then we get:
["bar", "bar"]
["bar"]
like we expect since we pushed f
‘s returned result to the result
array.
But when we have something like:
function f() {
return "global";
}
function foo(x) {
var result = [];
if (x) {
function f() {
return "bar";
}
result.push(f());
}
result.push(f());
return result;
}
console.log(foo(true));
console.log(foo(false));
Then the 2nd foo
call won’t run since f
is assumed to be the one inside.
This is something that would trip many people up.
The code function will still be allowed by JavaScript engines, but we get weird results like this.
Functions declarations shouldn’t be inside another block or function, so we should avoid this.
What we should do is either keep the inner function outer, or we can assign it to a local variable.
For instance, we can write:
function f() {
return "global";
}
function test(x) {
var result = [];
if (x) {
const g = f;
result.push(g());
}
result.push(f());
return result;
}
Then there won’t be any issues with scoping.
Don’t Create Local Variable with eval
eval
should definitely never be used because of its security and performance issues.
Another way that eval
is bad is creating local variables with it.
For instance, if we have:
function foo(x) {
eval("var y = x;");
return y;
}
console.log(foo("bar"));
Then we see 'bar'
logged.
We created the variable y
by assigning parameter x
to it in the string that we passed into eval
.
The problem arises if we make the eval
call conditional.
For instance, if we have:
var y = "global";
function foo(x) {
if (x) {
eval("var y = 'local';");
}
return y;
}
console.log(foo(true));
console.log(foo(false));
then the scoping is done according to the condition that we have in foo
.
This is definitely a problem since we’ve to go through the code and the code is a string.
Another way that’s bad is that we have:
var y = "global";
function bar(src) {
eval(src);
return y;
}
console.log(bar("var y = 'bar';"));
console.log(bar("var z = 'bar';"));
A string is passed into the bar
fucntion and we run eval
with it.
This pollutes the bar
function’s scope with extra variables defined from the outside.
This is even more confusing.
These are more reasons we shouldn’t use eval
for any purpose.
Conclusion
We shouldn’t have function declarations within another block.
It’s not valid JavaScript but it’s still allowed.
Also, we shouldn’t use eval
in any situation.